iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0
Mobile Development

從零開始學React Native系列 第 20

【從零開始學React Native】19. 創建Todo Tracker——app設置並連接到parse server (中)

  • 分享至 

  • xImage
  •  

打開Parse Dashboard
![[Pasted image 20241004231433.png]]
點擊Create a class來創建Class,命名成Task並創建
![[Pasted image 20241004231522.png]]

目前出現了一些錯誤,我們進行修改。

// src\stores\atoms.ts
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
import { Task, User } from '../types';
import { TaskService } from '../services/task.service';
import { UserService } from '../services/user.service';
import { MMKVStorage } from './mmkvStorage';

// Create async atoms for user-related data
export const userAtom = atom(async () => await UserService.getUser());
export const isLoggedInAtom = atom(async () => await UserService.isLoggedIn());
export const tokenAtom = atom(async () => await UserService.getToken());

// Create an async atom for tasks
export const tasksAtom = atom(async () => await TaskService.getTasks());

// Create atoms with storage for persistent data
export const persistentUserAtom = atomWithStorage<User | null>('user', null, MMKVStorage);
export const persistentIsLoggedInAtom = atomWithStorage<boolean>('isLoggedIn', false, MMKVStorage);
export const persistentTokenAtom = atomWithStorage<string | null>('token', null, MMKVStorage);

修正我們的Page

// src\pages\home.page.tsx
import React, { useCallback, useEffect } from 'react';
import { View, Text, TextInput, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
import { Colors } from 'react-native/Libraries/NewAppScreen';
import { Task } from '../types';
import { Swipeable } from 'react-native-gesture-handler';
import { useAtom } from 'jotai';
import { tasksAtom } from '../stores/atoms';
import { TaskService } from '../services/task.service';

// ... 保持 styles 不變 ...

type HomePageProps = {
  navigation: any;
};

const HomePage: React.FC<HomePageProps> = ({navigation}) => {
  const [tasks, setTasks] = useAtom(tasksAtom);

  useEffect(() => {
    const fetchTasks = async () => {
      const loadedTasks = await TaskService.getTasks();
      setTasks(loadedTasks);
    };
    fetchTasks();
  }, [setTasks]);

  const toggleTaskStatus = useCallback(async (id: string) => {
    const updatedTasks = tasks.map(task =>
      task.id === id ? { ...task, isDone: !task.isDone } : task
    );
    setTasks(updatedTasks);
    await TaskService.saveTasks(updatedTasks);
  }, [tasks, setTasks]);

  const deleteTask = useCallback(async (id: string) => {
    const updatedTasks = tasks.filter(task => task.id !== id);
    setTasks(updatedTasks);
    await TaskService.deleteTask(id);
  }, [tasks, setTasks]);

  // ... 保持 renderRightActions 和 renderTask 不變 ...

  return (
    <View style={styles.container}>
      <Text style={styles.title}>任務列表</Text>
      <TextInput
        style={styles.searchBar}
        placeholder="搜尋欄"
        placeholderTextColor={Colors.dark}
      />
      <FlatList
        style={styles.taskList}
        data={tasks}
        renderItem={renderTask}
        keyExtractor={item => item.id}
      />
    </View>
  );
};

export default HomePage;
// src\pages\add-task.page.tsx
import React, { useState } from 'react';
import { View, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView, Alert } from 'react-native';
import { useSetAtom } from 'jotai';
import { tasksAtom } from '../stores/atoms';
import { Task, Tags } from '../types/index';
import DatePicker from 'react-native-date-picker';
import { TaskService } from '../services/task.service';

// ... 保持 styles 和其他 imports 不變 ...

const AddTaskPage: React.FC<AddTaskPageProps> = ({ navigation }) => {
  // ... 保持 state 變量不變 ...

  const setTasks = useSetAtom(tasksAtom);

  // ... 保持 validateTask 不變 ...

  const handleSubmit = async () => {
    const newTask: Task = {
      id: Date.now().toString(),
      title,
      startDate: startDate ? startDate.toISOString().split('T')[0] : null,
      endDate: endDate ? endDate.toISOString().split('T')[0] : null,
      description,
      isDone: false,
      tags,
      subTasks: [],
    };

    const validationErrors = validateTask(newTask);

    if (validationErrors.length > 0) {
      Alert.alert('Validation Error', validationErrors.join('\n'));
      return;
    }

    await TaskService.addTask(newTask);
    const updatedTasks = await TaskService.getTasks();
    setTasks(updatedTasks);
    
    // Reset form fields
    setTitle('');
    setDescription('');
    setStartDate(null);
    setEndDate(null);
    setTags([]);
    Alert.alert('Success', 'Task added successfully');
    navigation.goBack();
  };

  // ... 保持其他方法和 JSX 不變 ...
};

export default AddTaskPage;

(...待續)

心得

目前主要是將錯誤修正。並讓react native能連接上我們的parse server


上一篇
【從零開始學React Native】18. 創建Todo Tracker——app設置並連接到parse server (上)
系列文
從零開始學React Native20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言